#include <QVBoxLayout>
#include <QTimer>
#include <QMenu>
#include <QAction>
#include <QEventLoop>
#include <cassert>
#include "TaskList.h"


TaskList::TaskList(QWidget *parent) : QWidget(parent)
{
    m_layout = new QVBoxLayout(this);
    m_layout->setSpacing(10);
    setLayout(m_layout);

    m_minuteTimer = new QTimer(this);
    m_minuteTimer->setInterval(1000 * 60); // 每隔 1min 更新
    connect(m_minuteTimer, &QTimer::timeout, this, &TaskList::freshTaskItems);


    m_secondTimer = new QTimer(this);
    m_secondTimer->setInterval(1000); // 每隔 1s 更新
    connect(m_secondTimer, &QTimer::timeout, this, &TaskList::freshCountdownTaskItems);


    int alignMsec = (1001 - QTime::currentTime().msec()) % 1000; // 对齐到1ms
    QTimer::singleShot(alignMsec, m_minuteTimer, QOverload<>::of(&QTimer::start));
    QTimer::singleShot(alignMsec, m_secondTimer, QOverload<>::of(&QTimer::start));

}

inline int compareModes(TaskItem::Mode a, TaskItem::Mode b)
{

    if (a == TaskItem::Bell)
        a = TaskItem::NoMode;
    if (b == TaskItem::Bell)
        b = TaskItem::NoMode;
    return int(a) - int(b);
}

static int compareTaskItem(TaskItem *a, TaskItem *b)
{

    if (a->isChecked() < b->isChecked())
    {
        return -1;
    }
    else if (a->isChecked() > b->isChecked())
    {
        return 1;
    }
    else
    {
        if (compareModes(a->getMode(), b->getMode()) > 0)
        {
            return -1;
        }
        else if (compareModes(a->getMode(), b->getMode()) < 0)
        {
            return 1;
        }
        else
        {
            if (a->getBeginDateTime() < b->getBeginDateTime())
            {
                return -1;
            }
            else if (a->getBeginDateTime() > b->getBeginDateTime())
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
    }
}


//传入一对迭代器，标准的插入排序
static void InsertionSort(QList<TaskItem*>::iterator begin, QList<TaskItem*>::iterator end)
{
    for (auto p1 = begin; p1 != end; ++p1)
    {
        auto p2 = p1;
        while ((p2 != begin) && compareTaskItem(*(p2-1), *p2) > 0)
        {
            TaskItem *temp = *(p2);
            *p2 = *(p2-1);
            *(p2-1) = temp;
            --p2;
        }
    }
}


void TaskList::setTasks(const QVector<ScheduleDataInfo> &tasks)
{
    m_minuteTimer->stop();
    m_secondTimer->stop();

    if (!m_items.isEmpty())
    {
        QEventLoop loop;
        for (auto taskItem : m_items)
        {
            disconnect(taskItem, &TaskItem::faded, nullptr, nullptr);
            taskItem->fadeAnimate();
        }
        connect(m_items.first(), &TaskItem::faded, &loop, &QEventLoop::quit);
        loop.exec();
        for (auto taskItem : m_items)
        {
            taskItem->hide();
            m_layout->removeWidget(taskItem);
            taskItem->deleteLater();
        }
    }

    m_items.clear();

    for (const ScheduleDataInfo &task : tasks)
    {
        TaskItem *taskItem = new TaskItem;
        taskItem->setTask(task);
        connect(taskItem, &TaskItem::faded, this, &TaskList::onItemFaded);
        connect(taskItem, &TaskItem::stateChanged, this, &TaskList::moveTaskItems);
        m_items.append(taskItem);
    }
    InsertionSort(m_items.begin(), m_items.end());
    for (auto taskItem : m_items)
    {
        m_layout->addWidget(taskItem);
        taskItem->show();
        taskItem->bloomAnimate();
    }

    adjustSize();

    m_minuteTimer->start();
    m_secondTimer->start();
}


void TaskList::moveTaskItems()
{
    TaskItem *item = qobject_cast<TaskItem *>(sender());
    assert(item);
    int index1 = m_items.indexOf(item);
    InsertionSort(m_items.begin(), m_items.end());
    int index2 = m_items.indexOf(item);
    if (index1 != index2)
    {
        item->fadeAnimate();
    }
    // bug 同时点击多个Item，时序问题

}

void TaskList::onSetTaskMode()
{

}

void TaskList::showMenu(QPoint globalPos)
{
    m_menu->exec(globalPos);
}

void TaskList::onItemFaded()
{
    TaskItem *item = qobject_cast<TaskItem *>(sender());
    assert(item);
    m_layout->removeWidget(item);
    m_layout->insertWidget(m_items.indexOf(item), item);
    item->bloomAnimate();
}

void TaskList::freshTaskItems()
{
    QList<TaskItem *> list = m_items;
    for (const auto taskItem : m_items)
    {
        int mode = taskItem->getMode();
        if (mode != TaskItem::CountdownTimer && mode != TaskItem::CountdownProcess)
            taskItem->refreshMode();
    }

}

void TaskList::freshCountdownTaskItems()
{
    for (const auto taskItem : m_items)
    {
        int mode = taskItem->getMode();
        if (mode == TaskItem::CountdownTimer || mode == TaskItem::CountdownProcess)
            taskItem->onCountdown();
        else
            break;
    }
}


